package hr.ctg.domain.action.korisnik;

import hr.ctg.domain.model.Korisnik;
import hr.ctg.domain.model.Rola;

import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectOne;
import javax.faces.component.html.HtmlInputSecret;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.persistence.EntityManager;

import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Transactional;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.faces.Renderer;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;
import org.jboss.seam.util.Base64;

import com.sun.faces.util.MessageFactory;

@Name("registerAction")
public class RegisterAction {
	@Logger
	Log log;

	@In(required = false)
	private EntityManager entityManager;

	@In
	private Renderer renderer;

	@In(required = false)
	private FacesMessages facesMessages;

	@In
	private Map<String, String> messages;

	@In(required = false)
	private Korisnik korisnik;

	@In
	Identity identity;

	private String username;
	private Rola rola = new Rola();
	private byte[] logo;
	private String tipLoga;

	private UISelectOne tipKorisnika;

	@End
	@Transactional
	public String register() {
		rola = entityManager.find(Rola.class, rola.getIdRole());
		rola.getKorisniks().add(korisnik);
		korisnik.getRolas().add(rola);
		entityManager.persist(korisnik);
		log.info("Korisnik #{korisnik.email} je registriran");
		try {
			log
					.info("Slanje verifikacijski emaila za korisnika #{korisnik.email}");
			renderer.render("/templates/mail/register.xhtml");
			facesMessages.addFromResourceBundle("message.initial.registration");
			log
					.info("Verifikacijski email za korisnika #{korisnik.email} je poslan");
		} catch (final Exception e) {
			log
					.error(
							"Slanje verifikacijskog emaila za korisnika #{korisnik.email} nije uspjelo",
							e);
			facesMessages.addFromResourceBundle(FacesMessage.SEVERITY_ERROR,
					"message.initial_registration.mail_send_failed");
			// throw new SystemException(e);
		}

		return "note";
	}

	public void checkUsername(final FacesContext facesContext,
			final UIComponent uiComponent, final Object object) {
		if (entityManager.createNamedQuery("Korisnik.findByUsername")
				.setParameter(1, object).getResultList().size() > 0) {
			throw new hr.ctg.domain.action.exception.ValidatorException(
					new FacesMessage(messages
							.get("message.username.already.exists")));
		}
	}

	public void validatePassword(final FacesContext facesContext,
			final UIComponent uiComponent, final Object object)
			throws ValidatorException {
		final String confirmPassword = (String) object;

		final String password = (String) ((HtmlInputSecret) facesContext
				.getViewRoot().findComponent(
						"registerForm:passwordDecoration:password")).getValue();

		if (password != null && confirmPassword != null
				&& !password.equals(confirmPassword)) {
			throw new ValidatorException(new FacesMessage(messages
					.get("message.password.confirm.not.match")));
		}

	}

	public void validateLength(final FacesContext facesContext,
			final UIComponent uiComponent, final Object object)
			throws ValidatorException {
		int desiredLength = 0;
		final String inputValue = (String) object;
		String id = uiComponent.getId();
		log.debug("Validiram duljinu polja ID=" + id);
		if ("adresa".equals(id))
			desiredLength = 20;
		if (desiredLength < inputValue.length()) {
			throw new ValidatorException(MessageFactory.getMessage(
					facesContext, "message.validation.field.length.max", ""
							+ desiredLength));
		}
	}

	@SuppressWarnings("unchecked")
	public void checkEmail(final FacesContext facesContext,
			final UIComponent uiComponent, final Object object) {
		if (entityManager.createNamedQuery("Korisnik.findByEmail")
				.setParameter(1, object).getResultList().size() > 0) {
			throw new hr.ctg.domain.action.exception.ValidatorException(
					new FacesMessage(messages
							.get("message.email.already.exists")));
		}

		final ClassValidator<Korisnik> emailValidator = new ClassValidator(
				Korisnik.class);

		// only get city property invalid values
		final Korisnik korisnik = new Korisnik();
		korisnik.setEmail(object.toString());
		final InvalidValue[] validationMessages = emailValidator
				.getInvalidValues(korisnik, "email");
		if (validationMessages.length > 0) {
			throw new hr.ctg.domain.action.exception.ValidatorException(
					new FacesMessage(validationMessages[0].getMessage()));
		}
	}

	@Transactional
	public String activate() {
		final Korisnik korisnik = (Korisnik) entityManager.createNamedQuery(
				"Korisnik.findByUsername").setParameter(1, username)
				.getSingleResult();

		korisnik.setAktivan(true);
		entityManager.merge(korisnik);
		log.info("Korisnik #{korisnik.email} je aktiviran");

		facesMessages.add("message.account.activated");

		return "login";
	}

	public String getKey() {
		return username;
	}

	public void setKey(final String key) {
		username = new String(Base64.decode(key));
	}

	public Rola getRola() {
		return rola;
	}

	public void setRola(final Rola rola) {
		this.rola = rola;
	}

	public void addLogo() {
		if (logo != null) {
			korisnik.setLogo(logo);
			korisnik.setTipLoga(tipLoga);
		}
		// FacesContext.getCurrentInstance().renderResponse();
	}

	public byte[] getLogo() {
		return logo;
	}

	public void setLogo(final byte[] logo) {
		this.logo = logo;
	}

	public String getTipLoga() {
		return tipLoga;
	}

	public void setTipLoga(final String tipLoga) {
		this.tipLoga = tipLoga;
	}

	public UISelectOne getTipKorisnika() {
		return tipKorisnika;
	}

	public void setTipKorisnika(final UISelectOne tipKorisnika) {
		this.tipKorisnika = tipKorisnika;
	}
}
